package com.jic.veteran.portal.service.impl;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.date.DateUnit;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONConfig;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import com.github.pagehelper.PageHelper;
import com.jic.veteran.common.service.RedisService;
import com.jic.veteran.mapper.PayInfoMapper;
import com.jic.veteran.mapper.ProjectDonationDetailMapper;
import com.jic.veteran.mapper.UmsMemberMapper;
import com.jic.veteran.model.*;
import com.jic.veteran.portal.domain.ProjectDto;
import com.jic.veteran.portal.domain.RecentDonateDto;
import com.jic.veteran.portal.service.UmsMemberCacheService;
import com.jic.veteran.security.annotation.CacheException;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;

@Slf4j
@Service
public class UmsMemberCacheServiceImpl implements UmsMemberCacheService {
    @Autowired
    private RedisService redisService;
    @Autowired
    private UmsMemberMapper memberMapper;
    @Autowired
    private ProjectDonationDetailMapper projectDonationDetailMapper;
    @Autowired
    private PayInfoMapper payInfoMapper;
    @Value("${redis.database}")
    private String REDIS_DATABASE;
    @Value("${redis.expire.common}")
    private Long REDIS_EXPIRE;
    @Value("${redis.expire.authCode}")
    private Long REDIS_EXPIRE_AUTH_CODE;
    @Value("${redis.key.member}")
    private String REDIS_KEY_MEMBER;
    @Value("${redis.key.authCode}")
    private String REDIS_KEY_AUTH_CODE;
    @Value("${redis.key.projectId}")
    private String REDIS_KEY_PROJECT_ID;
    @Value("${redis.key.projectList}")
    private String REDIS_KEY_PROJECT_LIST;
    @Value("${redis.key.donationList}")
    private String REDIS_KEY_PROJECT_DONATE_LIST;
    @Value("${redis.key.payBasicInfo}")
    private String REDIS_KEY_PAY_BASIC_INFO;
    @Value("${redis.key.cmsArticleList}")
    private String REDIS_KEY_CMS_ARTICLE_LIST;
    @Value("${redis.key.personDonationList}")
    private String REDIS_KEY_PERSON_DONATION_LIST;
    @Value("${redis.key.personCertificateList}")
    private String REDIS_KEY_PERSON_CERTIFICATE_LIST;
    @Value("${redis.key.bigScreenTime}")
    private String REDIS_KEY_BIG_SCREEN_TIME;

    @Override
    public void delMember(Long memberId) {
        UmsMember umsMember = memberMapper.selectByPrimaryKey(memberId);
        if (umsMember != null) {
            String key = REDIS_DATABASE + ":" + REDIS_KEY_MEMBER + ":" + umsMember.getUsername();
            redisService.del(key);
        }
    }

    @Override
    public UmsMember getMember(String username) {
        String key = REDIS_DATABASE + ":" + REDIS_KEY_MEMBER + ":" + username;
        return (UmsMember) redisService.get(key);
    }

    @Override
    public UmsMember getPhone(Long phone) {
        String key = REDIS_DATABASE + ":" + REDIS_KEY_MEMBER + ":" + phone;
        return (UmsMember) redisService.get(key);
    }

    @Override
    public void setMember(UmsMember member) {
        String key = REDIS_DATABASE + ":" + REDIS_KEY_MEMBER + ":" + member.getUsername();
        redisService.set(key, member, REDIS_EXPIRE);
    }

    @CacheException
    @Override
    public void setAuthCode(String telephone, String authCode) {
        String key = REDIS_DATABASE + ":" + REDIS_KEY_AUTH_CODE + ":" + telephone;
        redisService.set(key, authCode, REDIS_EXPIRE_AUTH_CODE);
    }

    @CacheException
    @Override
    public String getAuthCode(String telephone) {
        String key = REDIS_DATABASE + ":" + REDIS_KEY_AUTH_CODE + ":" + telephone;
        return (String) redisService.get(key);
    }

    @CacheException
    @Override
    public String getProject(Long id) {
        String key = REDIS_DATABASE + ":" + REDIS_KEY_PROJECT_ID + ":" + id;
        return (String) redisService.get(key);
    }

    @Override
    public String getProjectByProjectId(String projectId) {
        String key = REDIS_DATABASE + ":" + REDIS_KEY_PROJECT_ID + ":" + projectId;
        return (String) redisService.get(key);
    }

    @CacheException
    @Override
    public List<ProjectBasic> getProjectList() {
        String key = REDIS_DATABASE + ":" + REDIS_KEY_PROJECT_LIST;
        List<ProjectBasic> projectDtoList = redisService.sMembers(key).stream().map(
                member -> {
                    return JSONUtil.toBean((String) member, ProjectBasic.class);
                }
        ).collect(Collectors.toList());
        return projectDtoList;
    }

    @Override
    public void setProjectDtoList(List<ProjectBasic> projectBasicList) {
        String key = REDIS_DATABASE + ":" + REDIS_KEY_PROJECT_LIST;
        for (ProjectBasic projectBasic : projectBasicList) {
            JSONObject jsonObject = JSONUtil.parseObj(projectBasic, JSONConfig.create().setOrder(true).setDateFormat("yyyy-MM-dd HH:mm:ss"));
            String value = jsonObject.toString();
            log.info("project list value : {}", value);
            if (!redisService.sIsMember(key, value)) {
                redisService.sAdd(key, value);
            }
        }
    }

    @Override
    public void setProject(ProjectDto projectDto) {
        String keyId = REDIS_DATABASE + ":" + REDIS_KEY_PROJECT_ID + ":" + projectDto.getProjectBasic().getId();
        String keyProjectId = REDIS_DATABASE + ":" + REDIS_KEY_PROJECT_ID + ":" + projectDto.getProjectBasic().getProjectId();
        JSONObject jsonObject = JSONUtil.parseObj(projectDto);
        jsonObject.setDateFormat("yyyy-MM-dd HH:mm:ss");
        redisService.set(keyId, JSONUtil.toJsonStr(jsonObject));
        redisService.set(keyProjectId, JSONUtil.toJsonStr(jsonObject));
    }

    @Override
    public void lPushLimit(ProjectDonationDetail projectDonationDetail) {
        if (null != projectDonationDetail) {
            RecentDonateDto recentDonateDto = new RecentDonateDto();
            recentDonateDto.setProjectId(projectDonationDetail.getProjectId());
            recentDonateDto.setProjectName(projectDonationDetail.getProjectName());
            recentDonateDto.setFinishTime(projectDonationDetail.getDonationTime());
            recentDonateDto.setNickName(projectDonationDetail.getUserName());
            UmsMember umsMember = getMember(projectDonationDetail.getUserId());
            if (null != umsMember) {
                recentDonateDto.setAvatarUrl(umsMember.getAvatarUrl());
            }
            recentDonateDto.setOpenid(projectDonationDetail.getUserId());
            recentDonateDto.setTrxamt(projectDonationDetail.getDonationAmount());
            String key = REDIS_DATABASE + ":" + REDIS_KEY_PROJECT_DONATE_LIST + ":" + projectDonationDetail.getProjectId();
            redisService.lPush(key, recentDonateDto);
            redisService.lTrim(key, 0, 4);
        }
    }

    @Override
    public List<RecentDonateDto> getRecentDonate(String projectId) {
        List<RecentDonateDto> recentDonateDtoList = new ArrayList<>();
        String key = REDIS_DATABASE + ":" + REDIS_KEY_PROJECT_DONATE_LIST + ":" + projectId;
        Long lSize = redisService.lSize(key);
        if (lSize > 0) {
            List<Object> lRange = redisService.lRange(key, 0, 4);
            for (Object object : lRange) {
                RecentDonateDto recentDonateDto = (RecentDonateDto) object;
                long between = DateUtil.between(recentDonateDto.getFinishTime(), DateUtil.date(), DateUnit.MINUTE);
                recentDonateDto.setBetweenTime(between + "分钟");
                if (between >= 60) {
                    between = DateUtil.between(recentDonateDto.getFinishTime(), DateUtil.date(), DateUnit.HOUR);
                    recentDonateDto.setBetweenTime(between + "小时");
                }
                recentDonateDtoList.add(recentDonateDto);
            }
        } else {
            PageHelper.startPage(1, 5);
            ProjectDonationDetailExample projectDonationDetailExample = new ProjectDonationDetailExample();
            if (StrUtil.isNotEmpty(projectId)) {
                projectDonationDetailExample.createCriteria().andProjectIdEqualTo(projectId);
            }
            projectDonationDetailExample.setOrderByClause("donation_time desc");
            List<ProjectDonationDetail> projectDonationDetailList = projectDonationDetailMapper.selectByExample(projectDonationDetailExample);
            for (ProjectDonationDetail projectDonationDetail : CollectionUtil.reverse(projectDonationDetailList)) {
                lPushLimit(projectDonationDetail);
            }
            return getRecentDonate(projectId);
        }
        return recentDonateDtoList;
    }

    @Override
    public PayInfo getPayInfo() {
        String key = REDIS_DATABASE + ":" + REDIS_KEY_PAY_BASIC_INFO;
        String value = (String) redisService.get(key);
        if (StrUtil.isNotEmpty(value)) {
            return JSONUtil.toBean(value, PayInfo.class);
        }
        PayInfo payInfo = payInfoMapper.getPayInfoStatus();
        if (payInfo != null) {
            redisService.set(key, JSONUtil.toJsonStr(payInfo));
        } else {
            redisService.set(key, null);
        }
        return payInfo;
    }

    @Override
    public List<CmsArticleInfo> getCmsArticleInfoList(String articleType) {
        String key = REDIS_DATABASE + ":" + REDIS_KEY_CMS_ARTICLE_LIST + ":" + articleType;
        List<CmsArticleInfo> cmsArticleInfoList = redisService.sMembers(key).stream().map(
                member -> {
                    return JSONUtil.toBean((String) member, CmsArticleInfo.class);
                }
        ).collect(Collectors.toList());
        return cmsArticleInfoList;
    }

    @Override
    public void setCmsArticleInfoList(List<CmsArticleInfo> cmsArticleInfoList) {
        for (CmsArticleInfo cmsArticleInfo : cmsArticleInfoList) {
            JSONObject jsonObject = JSONUtil.parseObj(cmsArticleInfo, JSONConfig.create().setOrder(true).setDateFormat("yyyy-MM-dd HH:mm:ss"));
            String value = jsonObject.toString();
            log.info("cmsArticleInfo list value : {}", value);
            String key = REDIS_DATABASE + ":" + REDIS_KEY_CMS_ARTICLE_LIST + ":" + cmsArticleInfo.getArticleType();
            if (!redisService.sIsMember(key, value)) {
                redisService.sAdd(key, value);
            }
        }
    }

    @Override
    public List<ProjectDonationDetail> getPersonDonationList(String openId) {
        String key = REDIS_DATABASE + ":" + REDIS_KEY_PERSON_DONATION_LIST;
        String hashKey = REDIS_DATABASE + ":" + REDIS_KEY_PERSON_DONATION_LIST + ":" + openId;
        List<ProjectDonationDetail> projectDonationDetailList = (List<ProjectDonationDetail>) redisService.hGet(key,hashKey);
        return projectDonationDetailList;
    }

    @Override
    public void setPersonDonationList(ProjectDonationDetail projectDonationDetail) {
        String key = REDIS_DATABASE + ":" + REDIS_KEY_PERSON_DONATION_LIST;
        String hashKey = REDIS_DATABASE + ":" + REDIS_KEY_PERSON_DONATION_LIST + ":" + projectDonationDetail.getUserId();
        List<ProjectDonationDetail> projectDonationDetailList = (List<ProjectDonationDetail>) redisService.hGet(key,hashKey);
        if(projectDonationDetailList !=null && !projectDonationDetailList.isEmpty()) {
            projectDonationDetailList.add(projectDonationDetail);
        } else {
            projectDonationDetailList = new ArrayList<ProjectDonationDetail>();
            projectDonationDetailList.add(projectDonationDetail);
        }
        redisService.hSet(key,hashKey,projectDonationDetailList);
    }

    @Override
    public void setPersonDonationAllList(String openId,List<ProjectDonationDetail> projectDonationDetailList) {
        String key = REDIS_DATABASE + ":" + REDIS_KEY_PERSON_DONATION_LIST;
        String hashKey = REDIS_DATABASE + ":" + REDIS_KEY_PERSON_DONATION_LIST + ":" + openId;
        redisService.hSet(key,hashKey,projectDonationDetailList);
    }

    @Override
    public List<JSONObject> getPersonCertificateList(String openId) {
        String key = REDIS_DATABASE + ":" + REDIS_KEY_PERSON_CERTIFICATE_LIST;
        String hashKey = REDIS_DATABASE + ":" + REDIS_KEY_PERSON_CERTIFICATE_LIST + ":" + openId;
        List<JSONObject> result = (List<JSONObject>) redisService.hGet(key,hashKey);
        return result;
    }

    @Override
    public void setPersonCertificateList(String openId) {
        String key = REDIS_DATABASE + ":" + REDIS_KEY_PERSON_CERTIFICATE_LIST;
        String hashKey = REDIS_DATABASE + ":" + REDIS_KEY_PERSON_CERTIFICATE_LIST + ":" + openId;
    }

    @Override
    public void setPersonCertificateAllList(String openId,List<JSONObject> list) {
        String key = REDIS_DATABASE + ":" + REDIS_KEY_PERSON_CERTIFICATE_LIST;
        String hashKey = REDIS_DATABASE + ":" + REDIS_KEY_PERSON_CERTIFICATE_LIST + ":" + openId;
        redisService.hSet(key,hashKey,list);
    }

    @Override
    public String getBigScreenTime() {
        String key = REDIS_DATABASE + ":" + REDIS_KEY_BIG_SCREEN_TIME;
        Object value = redisService.get(key);
        if(ObjectUtil.isNotEmpty(value)) {
            return (String) value;
        }
        return null;
    }
}
